/* -----------------------------------------------------------------------------
 * PROJECT    : net.lwf
 * FILE       : WordImageFactory.java
 *
 * HISTORY:
 * Date          Author                        Description
 * ----------------------------------------------------------------------------- 
 * Dec 19, 2008       Raghu Sarraff			       Created
 */
package lwf.factory;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import net.lwf.common.util.SortingUtil;
import net.lwf.handler.util.ImageFileFolderReader;

import lwf.handler.entities.WordImage;

/**
 * Type the class description here
 *  
 */
public class WordImageFactory {
	
	private static WordImageFactory instance = null;
	private String imageFolder;
	private Map wordimages;
	private Map mapallwordimages;
	private Map filteredimagewords;
	private List imageWords;
	private Map mapalphabetwords = null;
	
	private WordImageFactory() {

	}
	
	public synchronized final static WordImageFactory getInstance(){
		if (instance == null) {
			instance = new WordImageFactory();
		}
		return instance;
	}

	//-----------------------------------------------------------------------------------
	// This method is called ONLY from the Initializing servlet
	//-----------------------------------------------------------------------------------
	
	/**
	 * @param imagefolder The imagefolder to set.
	 */
	public void setImageFolder(String _imagefolder) {
		if(this.imageFolder == null) {
			this.imageFolder = _imagefolder;	
		}
	}


	/**
	 * Gets the map of images.
	 * key = base image directory; Ex. animals, bullets, etc.
	 * value = Map of images, where key=word; value=Instances of WordImage
	 * 
	 * @return
	 */
	public Map getImageData() {
		if(this.wordimages == null) {
			init();
		}
		return this.wordimages;
	}
	
	private void init() {
		File file = new File(this.imageFolder);
		this.wordimages = ImageFileFolderReader.getMappedFileListing(file);
		processAllWordImages();		
	}
	
	/**
	 * Key is the base directory name
	 * Value = Map of images, where key=word; value=Instances of WordImage
	 * 
	 * @param key
	 * @return
	 */
	public Map getWordImage(String key) {
		if(this.wordimages == null) {
			init();
		}
		if(wordimages.containsKey(key)) {
			return (Map) wordimages.get(key); 
		}
		return null;
	}
	
	/**
	 * Key is the word name
	 * Value = instances of WordImage
	 * 
	 * @return
	 */	
	public Map getAllWordImages() {
		if(this.mapallwordimages == null) {
			init();
		}
		return mapallwordimages;
	}
	
	//-----------------------------------------------------------------------------------
	// Customized methods
	//-----------------------------------------------------------------------------------
	/**
	 * Gets WordImage info for the given word.
	 * 
	 * @param word
	 * 
	 * @return
	 */
	public WordImage getImageByWord(String word) {
		String key = word.toLowerCase();
		if(this.mapallwordimages == null) {
			init();
		}
		if(mapallwordimages.containsKey(key)) {
			return (WordImage) mapallwordimages.get(key);
		}
		return null;
	}
	
	//Add the filter image folders;
	//Later read the same from the property file
	
	
	
	/**
	 * Filters the directories from the images and creates a separate
	 * map of image words.
	 * 
	 * @return
	 */
	public Map getFilteredImageWords() {
		String filterString = "bullets button math thankyou tabs time";
		if(filteredimagewords == null) {
			filteredimagewords = new HashMap();
			Iterator iterator = getImageData().entrySet().iterator();
			while(iterator.hasNext()) {
				Map.Entry mapentry = (Map.Entry) iterator.next();
				String key = (String) mapentry.getKey();
                //key is the directory name in the image directory
				if(key != null && key.trim().length() != 0) {
					key = key.trim();
					if(filterString.indexOf(key) == -1) {
						Map subdirinfo = (Map) mapentry.getValue();
						if(subdirinfo != null && subdirinfo.size() != 0) {
							filteredimagewords.putAll(subdirinfo);
						}					
					}
				}

			}
		}		
		return filteredimagewords;
	}
	
	/**
	 * Processes all image words and generates a list of the words (only names).
	 * 
	 * @return
	 */
	public List getImageWords() {
		if(imageWords == null) {
			imageWords = new ArrayList();
			Map filteredimagewords = getFilteredImageWords();
			imageWords = new ArrayList(filteredimagewords.size());
			Iterator iterator = filteredimagewords.entrySet().iterator();
			while(iterator.hasNext()) {
				Map.Entry mapentry = (Map.Entry) iterator.next();
				imageWords.add((String) mapentry.getKey());
			}
		}
		return imageWords;
	} //getImageWords
	
	/**
	 * Processes all image words and generates a list of the words (only names)in
	 * a given directory.
	 * 
	 * @param directory Directory/folder name
	 * @return
	 */
	public List getImageWords(String directory) {
		List wordsindirectory = new ArrayList();
		    Map directorydata = (Map) getImageData().get(directory);
			Iterator iterator = directorydata.entrySet().iterator();
			while(iterator.hasNext()) {
				Map.Entry mapentry = (Map.Entry) iterator.next();
				wordsindirectory.add((String) mapentry.getKey());
			}
		return wordsindirectory;
	} //getImageWords
	
	
	/**
	 * Gets the image words (names ONLY) for the given alphabet.
	 * Each word is sorted by its length.
	 * 
	 * @param alphabet Alphabet (one character)
	 * 
	 * @return
	 */
	public List getWordsByAlphabet(String alphabet) {
		List words = null;
		if(mapalphabetwords == null) {
			mapalphabetwords = getAlphabetWords();
		}
		if(mapalphabetwords != null) {
			words = (List) mapalphabetwords.get(alphabet.toLowerCase());
			words = SortingUtil.sortByLength(words);
		}
		return words;
	}
	
	//-----------------------------------------------------------------------------------
	// Private methods
	//-----------------------------------------------------------------------------------
	/**
	 * processes all data and populate one object holding the 
	 * word image info.
	 * 
	 * Key is the word name
	 * Value = instances of WordImage 
	 */
	private void processAllWordImages() {
		mapallwordimages = new HashMap();
		if(wordimages != null && wordimages.size() != 0) {
			Iterator iterator = wordimages.entrySet().iterator();
			while(iterator.hasNext()) {
				Map.Entry mapentry = (Map.Entry) iterator.next();
				//Ignoring the key and considering the value
				Map subdirinfo = (Map) mapentry.getValue();
				if(subdirinfo != null && subdirinfo.size() != 0) {
					mapallwordimages.putAll(subdirinfo);
				}
			}
		}
	}
	
	/**
	 * Gets the image words (only names) sorted by alphabet.
	 * 
	 * @return
	 */
	private Map getAlphabetWords() {
		if(mapalphabetwords == null) {
			mapalphabetwords = new TreeMap();
			List lstimagewords = getImageWords();
			for(int i=0; i<lstimagewords.size(); i++) {
				String word = (String) lstimagewords.get(i);
				String startalphabet = word.substring(0,1);
				List lstalphawords = null;
				if(startalphabet.trim().length() != 0) {
					if(mapalphabetwords.containsKey(startalphabet.toLowerCase())) {
						lstalphawords = (List) mapalphabetwords.get(startalphabet.toLowerCase());
					}
					else {
						lstalphawords = new ArrayList();
					}
				}
				lstalphawords.add(word);
				Collections.sort(lstalphawords);
				mapalphabetwords.put(startalphabet, lstalphawords);
			}
		}
		return mapalphabetwords;
	} //getAlphabetWords
	
	
}

